using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
using System.Security.Policy;
using System.Security.Principal;
using System.ServiceModel;
using System.ServiceModel.Description;
using System.ServiceModel.Security;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using EnvDTE;
using EnvDTE80;
using Microsoft.Win32;
using SPVisualDev.Services;
using System.Runtime.InteropServices;

namespace SPVisualDev.VSAddin
{
    internal class Common
    {
		public const string C_MS_SHAREPOINT_XMLNS = "http://schemas.microsoft.com/sharepoint/";
		public const string C_MS_SHAREPOINT_EVENTS_NS = "http://schemas.microsoft.com/sharepoint/events";
        public const string C_PROJECT_EVENT_RECEIVER_CODE_PATH = "EventReceivers";
        public const string C_PROJECT_WEB_PART_CODE_PATH = "UI\\WebParts";

        public const string C_GLOBAL_CONFIG_KEY_PREFIX = "SPVisualDev_";
        public const string C_PROJECT_ID_VAR_NAME = "SPVisualDev_ProjID";
        public const string C_SHAREPOINT_ARTIFACTS_PROJECT_ID = "SharePointArtifactsProject";
        public const string C_GENERIC_PROJECT_ID = "Generic";
        public const string C_SETTINGS_FILE = "projsettings.xml";
        public const string C_SETTINGS_FILE_V2 = "spvisualdev_proj.spvdinfo";
        public const string C_SOLUTION_SETTINGS_FILE = "spvisualdev_sol.spvdinfo";
        public const string C_DEFAULT_TARGET_URL = "http://localhost";
        public const string C_DEFAULT_SP_MANAGED_PATH = "SPVisualDev";
        public const string C_IGNORE_FILE_TYPE_ON_PUSH_DOWN = ".cs;.vb";
        public const string C_SPDEVEXTENSIONS_ASSEMBLY_NAME = "SPDevExtensions, Version=1.0.0.1, Culture=neutral, PublicKeyToken=383c1a4a7bd8f1f3";
        public const string C_SPDEVEXTENSIONS_WSSTES_FEATURE_RECEIVER_CLASS = "SPDevExtensions.WSSTES.WSSFeatureReceiverBase";
        public const string C_SPDEVEXTENSIONS_FEATURE_PROPERTY_NAME = "WSSTES_AssemblyToLoad";
        public const string C_LOCAL_RESOURCE_IDENTIFIER = "_Res";
        public const string C_VBPROJ_GUID = "{B5E9BD33-6D3E-4B5D-925E-8A43B79820B4}";
        public const string C_CSPROJ_GUID = "{B5E9BD34-6D3E-4B5D-925E-8A43B79820B4}";
        public const string C_FEATURE_META_INFO_FILE_NAME = "metainfo.spvdinfo";
        public const string C_FEATURE_META_INFO_COMMENT = "This file is generated by SPVisualDev. It doesn't need to be included when deploying the solution or installing the feature. It will automatically be excluded when building a WSP package.";
        public const string C_REMOTE_MAIN_SVC_ADDRESS = "/SPVisualDevWinSvc/MainService";
        public const int C_WCF_MAIN_SVC_PORT = 5667;
        public const int C_WCF_MAX_RECEIVED_SIZE = 67108864;
        public const int C_WCF_CONNECTION_TIMEOUT_OPEN = 10;
        public const int C_WCF_CONNECTION_TIMEOUT_SEND = 180;
        public const int C_WCF_CONNECTION_TIMEOUT_RECEIVE = 180;
        public const int C_WCF_CONNECTION_TIMEOUT_CLOSE = 10;
        public const string C_SERVICE_MIN_VERSION = "2.1.0.1";
        public const string C_CRYPTO_KEY_CONTAINER_NAME = "SPVisualDev_RSA_Key";
        public const string C_CRYPTO_KEY_PROVIDER_NAME = "Microsoft Strong Cryptographic Provider";

        public static string EncryptUsingKeyContainer(string StringToEncrypt)
        {
            if (string.IsNullOrEmpty(StringToEncrypt))
                return StringToEncrypt;

            CspParameters cspParameters = new CspParameters();
            cspParameters.KeyContainerName = C_CRYPTO_KEY_CONTAINER_NAME;
            cspParameters.Flags = CspProviderFlags.UseDefaultKeyContainer;
            //cspParameters.ProviderName = C_CRYPTO_KEY_PROVIDER_NAME;

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParameters);

            byte[] b = rsa.Encrypt(Encoding.Unicode.GetBytes(StringToEncrypt), true);

            return Convert.ToBase64String(b);
        }

        public static string DecryptUsingKeyContainer(string StringToDecrypt)
        {
            if (string.IsNullOrEmpty(StringToDecrypt))
                return StringToDecrypt;

            CspParameters cspParameters = new CspParameters();
            cspParameters.KeyContainerName = C_CRYPTO_KEY_CONTAINER_NAME;
            cspParameters.Flags = CspProviderFlags.UseDefaultKeyContainer;
            //cspParameters.ProviderName = C_CRYPTO_KEY_PROVIDER_NAME;

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(cspParameters);
            byte[] b = rsa.Decrypt(Convert.FromBase64String(StringToDecrypt), true);

            return Encoding.Unicode.GetString(b);
        }

        public static int LaunchBrowser(string URL)
        {
            using (System.Diagnostics.Process p = new System.Diagnostics.Process())
            {
                p.StartInfo.Arguments = URL;
                p.StartInfo.FileName = "iexplore.exe";
                p.Start();

                return p.Id;
            }
        }

        public static void RefreshFeatureFile(SpecialProject specialProject, ProjectItem FeatureFolder)
        {
            FeatureManager manager = new FeatureManager(specialProject, FeatureFolder);
            manager.ReadContent();
            manager.WriteContent(false);
        }

        public static bool HasAssemblyReferenced(Project project, string AssemblyName)
        {
            VSLangProj.VSProject vsProj = project.Object as VSLangProj.VSProject;
            if (vsProj.References.Find(AssemblyName) != null)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static string GetItemTemplatePath(Project project, string Name, bool OwnTemplate)
        {
            string prefix = string.Empty;
            string template_path;
            if (project.CodeModel.Language.ToLower() == C_CSPROJ_GUID.ToLower())
            {
                if (OwnTemplate)
                    prefix = "CSharp ";

                template_path = ((Solution2)project.DTE.Solution).GetProjectItemTemplate(prefix + Name, "csproj");
            }
            else
            {
                if (OwnTemplate)
                    prefix = "VB ";

                template_path = ((Solution2)project.DTE.Solution).GetProjectItemTemplate(prefix + Name, "vbproj");
            }

            return template_path;
        }

        public static ConnectionDetailsStruct GetServiceConnection(SpecialProject specialProject)
        {
            ConnectionDetailsStruct details = new ConnectionDetailsStruct();

            string remote_server_address = string.Empty;
            string remote_server_port = string.Empty;
            string username = string.Empty;
            string password = string.Empty;

            bool bFlag = false;
            if (specialProject != null)
            {
                if (specialProject.GetUserSettingsValue("RemoteServerUse") == "True")
                {
                    remote_server_address = specialProject.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_ADDRESS);
                    remote_server_port = specialProject.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PORT);

                    if (specialProject.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_USE_DIFFERENT_CRED) == "True")
                    {
                        try
                        {
                            username = Common.DecryptUsingKeyContainer(specialProject.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USERNAME));
                            password = Common.DecryptUsingKeyContainer(specialProject.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PASSWORD));

                            if (username != null && username.StartsWith("SPVD;"))
                            {
                                username = username.Substring(5);
                            }
                            else
                            {
                                username = "";
                                password = "";
                            }
                        }
                        catch
                        {
                            username = "";
                            password = "";
                        }
                    }

                    bFlag = true;
                }
                else if (specialProject.SpecialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USE) == "True")
                {
                    return Common.GetServiceConnectionBySolution(specialProject.SpecialSolution);
                }
            }

            if (!bFlag)            
            {
                if (Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USE, true) == "True")
                {
                    remote_server_address = Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_ADDRESS, true);
                    remote_server_port = Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PORT, true);

                    if (Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_USE_DIFFERENT_CRED, true) == "True")
                    {
                        try
                        {
                            username = Common.DecryptUsingKeyContainer(Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USERNAME, false));
                            password = Common.DecryptUsingKeyContainer(Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PASSWORD, false));
                        }
                        catch
                        {
                            username = "";
                            password = "";
                        }
                    }
                }
                else
                {
                    remote_server_address = "";
                    remote_server_port = Common.C_WCF_MAIN_SVC_PORT.ToString();

                    if (!Connect.S_Client_Install)
                    {
                        if (!SharePointLibrary.CheckIf32bitOn64())
                        {
                            remote_server_port = "0";
                            details.UseInProc = true;
                        }
                    }
                    else
                    {
                        remote_server_port = "0";
                        //throw new Exception("No remote connection configured.");
                    }
                }
            }


            details.Address = remote_server_address;

            if (!string.IsNullOrEmpty(remote_server_port))
                details.Port = int.Parse(remote_server_port);

            details.UserName = username;
            details.Password = password;

            return details;
        }

        public static ConnectionDetailsStruct GetServiceConnectionBySolution(SpecialSolution specialSolution)
        {
            ConnectionDetailsStruct details = new ConnectionDetailsStruct();

            string remote_server_address = string.Empty;
            string remote_server_port = string.Empty;
            string username = string.Empty;
            string password = string.Empty;

            if (specialSolution.GetUserSettingsValue("RemoteServerUse") == "True")
            {
                remote_server_address = specialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_ADDRESS);
                remote_server_port = specialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PORT);

                if (specialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_USE_DIFFERENT_CRED) == "True")
                {
                    try
                    {
                        username = Common.DecryptUsingKeyContainer(specialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USERNAME));
                        password = Common.DecryptUsingKeyContainer(specialSolution.GetUserSettingsValue(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PASSWORD));

                        if (username != null && username.StartsWith("SPVD;"))
                        {
                            username = username.Substring(5);
                        }
                        else
                        {
                            username = "";
                            password = "";
                        }
                    }
                    catch
                    {
                        username = "";
                        password = "";
                    }
                }
            }

            else if (Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USE, true) == "True")
            {
                remote_server_address = Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_ADDRESS, true);
                remote_server_port = Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PORT, true);

                if (Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_USE_DIFFERENT_CRED, true) == "True")
                {
                    try
                    {
                        username = Common.DecryptUsingKeyContainer(Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_USERNAME, false));
                        password = Common.DecryptUsingKeyContainer(Common.GetUserRegistryParam(SettingsPageRemote.C_PARAM_REMOTE_SERVER_PASSWORD, false));
                    }
                    catch
                    {
                        username = "";
                        password = "";
                    }
                }
            }
            else
            {
                remote_server_address = "";
                remote_server_port = Common.C_WCF_MAIN_SVC_PORT.ToString();

                if (!Connect.S_Client_Install)
                {
                    if (!SharePointLibrary.CheckIf32bitOn64())
                    {
                        remote_server_port = "0";
                        details.UseInProc = true;
                    }
                }
                else
                {
                    remote_server_port = "0";
                    //throw new Exception("No remote connection configured.");
                }
            }


            details.Address = remote_server_address;

            if (!string.IsNullOrEmpty(remote_server_port))
                details.Port = int.Parse(remote_server_port);

            details.UserName = username;
            details.Password = password;

            return details;
        }

        public static bool ShouldIgnoreFile(string FileName, string IgnoreFileExtensionsString)
        {
            if (IgnoreFileExtensionsString == null)
                IgnoreFileExtensionsString = C_IGNORE_FILE_TYPE_ON_PUSH_DOWN;

            if (IgnoreFileExtensionsString.IndexOf(".spvdinfo", StringComparison.InvariantCultureIgnoreCase) == -1)
                IgnoreFileExtensionsString += ";.spvdinfo";

            if (IgnoreFileExtensionsString == string.Empty || Path.GetExtension(FileName) == string.Empty)
                return false;

            string[] arr = IgnoreFileExtensionsString.Split(';');
            string result = Array.Find<string>(arr, delegate(string extension) {

                if (string.IsNullOrEmpty(extension))
                    return false;

                if (extension.ToLower().Trim() == Path.GetExtension(FileName).ToLower().Trim())
                    return true;
                else
                    return false;
            });

            return (result != null);
        }
        
        public static string FilterXmlString(string Xml)
        {
            return Xml.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
        }

        public static bool CompareAssemblyName(string AssemblyName1, string AssemblyName2)
        {
            if (AssemblyName1 == null)
                AssemblyName1 = string.Empty;

            if (AssemblyName2 == null)
                AssemblyName2 = string.Empty;

            return (AssemblyName1.Replace(" ", "") == AssemblyName2.Replace(" ", ""));
        }

        public static ProjectItem GetProjectItem(Project Proj, string Path, string PathSeparator)
        {
            string[] arr = Path.Split(new string[] { PathSeparator}, StringSplitOptions.RemoveEmptyEntries);
            ProjectItem ret = null;

            try
            {
                ret = Proj.ProjectItems.Item(arr[0]);
            }
            catch { }

            if (ret == null)
                return null;
            
            int i = 1;

            while (i < arr.Length)
            {
                try
                {
                    ret = ret.ProjectItems.Item(arr[i]);
                }
                catch 
                {
                    return null;
                }

                i++;
            }

            return ret;

        }

        public static void SetXmlAttribute(XmlElement element, string AttributeName, string Value)
        {
            SetXmlAttribute(element, AttributeName, Value, false);
        }
        
        public static void SetXmlAttribute(XmlElement element, string AttributeName, string Value, bool IgnoreIfEmptyAndNotExists)
        {
            XmlAttribute attribute = null;
            foreach (XmlAttribute a in element.Attributes)
            {
                if (string.Compare(a.Name, AttributeName, true) == 0)
                {
                    attribute = a;
                    break;
                }
            }

            if (attribute == null)
            {
                if (!IgnoreIfEmptyAndNotExists || !string.IsNullOrEmpty(Value))
                    element.SetAttribute(AttributeName, Value);
            }
            else
            {
                attribute.Value = Value;
            }
        }
        
        public static void SetXmlAttributeIgnoreIfValueMatches(XmlElement element, string AttributeName, string Value)
        {
            SetXmlAttributeIgnoreIfValueMatches(element, AttributeName, Value, false);
        }
        
        public static void SetXmlAttributeIgnoreIfValueMatches(XmlElement element, string AttributeName, string Value, bool IgnoreIfEmptyAndNotExists)
        {
            XmlAttribute attribute = null;
            foreach (XmlAttribute a in element.Attributes)
            {
                if (string.Compare(a.Name, AttributeName, true) == 0)
                {
                    attribute = a;
                    break;
                }
            }

            if (attribute == null)
            {
                if (!IgnoreIfEmptyAndNotExists || !string.IsNullOrEmpty(Value))
                    element.SetAttribute(AttributeName, Value);
            }
            else
            {
                if (string.Compare(Value, attribute.Value, true) != 0)
                    attribute.Value = Value;
            }
        }
        
        public static string GetXmlAttribute(XmlElement element, string AttributeName)
        {
            string ret = string.Empty;
            foreach (XmlAttribute attribute in element.Attributes)
            {
                if (string.Compare(attribute.Name, AttributeName, true) == 0)
                {
                    ret = attribute.Value;
                    break;
                }
            }

            return ret;
        }

        public static XmlElement GetXmlChildNodeByName(XmlNode element, string Name)
        {
            XmlNodeList list = (element as XmlElement).GetElementsByTagName(Name);
            if (list.Count > 0)
                return list[0] as XmlElement;
            else
                return null;
        }

        public static List<CodeClass> ExtractClassesFromCodeFile(ProjectItem CodeFile)
        {
            List<CodeClass> ret = new List<CodeClass>();

            FileCodeModel2 cm = CodeFile.FileCodeModel as FileCodeModel2;
            if (cm == null)
                return ret;

            CodeNamespace cdNameSpace = null;
            foreach (CodeElement element in cm.CodeElements)
            {
                if (element.Kind == vsCMElement.vsCMElementNamespace)
                {
                    cdNameSpace = element as CodeNamespace;
                    break;
                }
            }

            if (cdNameSpace == null)
                return ret;

            foreach (CodeElement element in cdNameSpace.Children)
            {
                if (element is CodeClass)
                {
                    ret.Add(element as CodeClass);
                }
            }

            return ret;
        }

        public static Guid GetFeatureIdForBuiltInListType(int ListType)
        {
            Guid ret;
            switch (ListType)
            {
                case 100:
                    ret = new Guid("00BFEA71-DE22-43B2-A848-C05709900100");
                    break;
                case 101:
                    ret = new Guid("00BFEA71-E717-4E80-AA17-D0C71B360101");
                    break;
                case 102:
                    ret = new Guid("00BFEA71-EB8A-40B1-80C7-506BE7590102");
                    break;
                case 103:
                    ret = new Guid("00BFEA71-2062-426C-90BF-714C59600103");
                    break;
                case 104:
                    ret = new Guid("00BFEA71-D1CE-42de-9C63-A44004CE0104");
                    break;
                case 105:
                    ret = new Guid("00BFEA71-7E6D-4186-9BA8-C047AC750105");
                    break;
                case 106:
                    ret = new Guid("00BFEA71-EC85-4903-972D-EBE475780106");
                    break;
                case 107:
                    ret = new Guid("00BFEA71-A83E-497E-9BA0-7A5C597D0107");
                    break;
                case 108:
                    ret = new Guid("00BFEA71-6A49-43FA-B535-D15C05500108");
                    break;
                case 109:
                    ret = new Guid("00BFEA71-52D4-45B3-B544-B1C71B620109");
                    break;
                case 110:
                    ret = new Guid("00BFEA71-F381-423D-B9D1-DA7A54C50110");
                    break;
                case 115:
                    ret = new Guid("00BFEA71-1E1D-4562-B56A-F05371BB0115");
                    break;
                case 118:
                    ret = new Guid("00BFEA71-2D77-4A75-9FCA-76516689E21A");
                    break;
                case 119:
                    ret = new Guid("00BFEA71-C796-4402-9F2F-0EB9A6E71B18");
                    break;
                case 120:
                    ret = new Guid("00BFEA71-3A1D-41D3-A0EE-651D11570120");
                    break;
                default:
                    ret = Guid.Empty;
                    break;
            }

            return ret;
        }

        public static void SetUserRegistryParam(string Parameter, string Value)
        {
            Registry.SetValue("HKEY_CURRENT_USER\\Software\\SPVisualDev", Parameter, Value);
        }

        public static string GetUserRegistryParam(string Parameter, bool bReturnNullIfNotExists)
        {
            string ret = Registry.GetValue("HKEY_CURRENT_USER\\Software\\SPVisualDev", Parameter, null) as string;

            if (ret == null && !bReturnNullIfNotExists)
                ret = string.Empty;
            
            return ret;
        }

        public static string GetAssemblyNameFromFile(string FilePath, bool suppressErrorMsg)
        {
            AppDomainSetup domaininfo = new AppDomainSetup();
            AppDomain newDomain = null;

            try
            {
                // Create application domain setup information for new application domain.
                domaininfo.ApplicationBase = System.Environment.CurrentDirectory;
                domaininfo.ApplicationName = "SPVisualDev_appl_" + Guid.NewGuid().ToString("N");

                // Create appdomain.
                newDomain = AppDomain.CreateDomain("SPVisualDev_appdomain_" + Guid.NewGuid().ToString("N"), null, domaininfo);

                // Load an assembly into the new application domain.
                Worker w = (Worker)newDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().GetName().FullName, "SPVisualDev.VSAddin.Worker");
                string asm_name = w.GetTargetAssemblyName(FilePath);

                return asm_name;
            }
            catch (Exception ex)
            {
                if (!suppressErrorMsg)
                    MessageBox.Show("Unable to fetch assembly name information. " + ex.ToString(), "Failure", MessageBoxButtons.OK, MessageBoxIcon.Error);

                throw;
            }
            finally
            {
                if (newDomain != null)
                    AppDomain.Unload(newDomain);
            }
        }

        public static void WriteStreamToFile(Stream SourceStream, string DestinationFile)
        {
            int bufferSize = 32768;
            using (FileStream fs = new FileStream(DestinationFile, FileMode.Create, FileAccess.Write, FileShare.None, bufferSize))
            {
                byte[] buffer = new byte[bufferSize];
                int c = 0;
                while ((c = SourceStream.Read(buffer, 0, bufferSize)) > 0)
                {
                    fs.Write(buffer, 0, c);
                }
            }
        }

        public static string GetTargetBuildAssemblyName(Project project, bool suppressErrorMsg)
        {
            return GetAssemblyNameFromFile(GetTargetPath(project), suppressErrorMsg);
        }

        public static bool HasBaseCodeClass(CodeClass codeClass, string BaseName)
        {
            while (codeClass.Bases.Count > 0)
            {
                codeClass = codeClass.Bases.Item(1) as CodeClass;

                if (codeClass == null)
                    return false;

                if (codeClass.Name == BaseName)
                    return true;
            }

            return false;
        }

        public static bool ProjectHasKeyFileAssigned(Project project)
        {
            string AssemblyOriginatorKeyFile = null;
            try
            {
                AssemblyOriginatorKeyFile = project.Properties.Item("AssemblyOriginatorKeyFile").Value as string;
            }
            catch { }

            if (!string.IsNullOrEmpty(AssemblyOriginatorKeyFile))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public static bool BuildProject(Project project, bool IgnoreIsDirtyFlag, bool IgnoreBuildError)
        {
//            _current_project_build = project;

            if (project.IsDirty || IgnoreIsDirtyFlag)
            {
                project.DTE.Solution.SolutionBuild.BuildProject(project.DTE.Solution.SolutionBuild.ActiveConfiguration.Name, project.UniqueName, true);
                if (project.DTE.Solution.SolutionBuild.LastBuildInfo != 0)
                {
                    string msg = "Error occured when project was built. Please view the build output window for more information.";

                    if (IgnoreBuildError)
                    {
                        MessageBox.Show(msg, "Project build error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                        return false;
                    }
                    else
                    {
                        throw new Exception(msg);
                    }
                }
            }

            return true;
        }

        public static bool CheckIfSpecialProject(Project Proj)
        {
            try
            {
                string id = Common.GetProjectGlobalConfigKey(Proj, Common.C_PROJECT_ID_VAR_NAME);
                return (!string.IsNullOrEmpty(id));
            }
            catch
            {
                return false;
            }
        }

        public static bool HasUnsavedOpenedDocuments(EnvDTE80.DTE2 dte)
        {
            bool bFlag = false;

            foreach (Document doc in dte.Documents)
            {
                ProjectItem item = doc.ProjectItem;
                if (item != null)
                {
                    if (item.get_IsOpen(Constants.vsViewKindAny))
                    {
                        if (item.IsDirty)
                        {
                            bFlag = true;
                            break;
                        }
                    }
                }
            }

            return bFlag;
        }

        private void ReplaceTextInItems(string SearchText, string ReplaceText, ProjectItem StartFolder, bool Recursive)
        {
            foreach (ProjectItem item in StartFolder.ProjectItems)
            {
                
            }
        }

        public static void ReplaceParametersInFile(string path, Hashtable replacementParameters)
        {
            string content;

            using (StreamReader sr = new StreamReader(path))
            {
                content = sr.ReadToEnd();
            }

            foreach (DictionaryEntry de in replacementParameters)
            {
                content = content.Replace(de.Key.ToString(), de.Value.ToString());
            }

            using (StreamWriter sw = new StreamWriter(path, false))
            {
                sw.Write(content);
            }
        }

        public static string GetProjectItemPath(ProjectItem Item)
        {
            return GetProjectItemPath(Item, false);
        }

        public static string GetProjectItemPath(ProjectItem Item, bool RelativeToProject)
        {
            string path = Item.Properties.Item("FullPath").Value.ToString();

            if (RelativeToProject)
            {
                string proj_path = Item.ContainingProject.Properties.Item("LocalPath").Value.ToString();
                if (proj_path.EndsWith("\\"))
                    path = path.Substring(proj_path.Length);
                else
                    path = path.Substring(proj_path.Length - 1);
            }

            return (path.EndsWith("\\")) ? path.Substring(0, path.Length - 1) : path;
        }

        public static Project GetProjectByName(Projects projects, string name)
        {
            foreach(Project p in projects)
            {
                if (p.Name == name)
                    return p;
            }

            return null;
        }

        public static string GetProjectPath(Project project)
        {
            return Path.GetDirectoryName(project.FullName);
        }

        public static string GetSafeName(string Folder, string SuggestedName)
        {
            int i = 0;

            string Suggested_name_without_extension = Path.GetFileNameWithoutExtension(SuggestedName);
            string Suggested_name_extension = Path.GetExtension(SuggestedName);
            
            SuggestedName = Suggested_name_without_extension + Suggested_name_extension;
            while (File.Exists(Folder + "\\" + SuggestedName) || Directory.Exists(Folder + "\\" + SuggestedName))
            {
                i++;
                SuggestedName = Suggested_name_without_extension + i.ToString() + Suggested_name_extension;
            }

            return SuggestedName;
        }

        public static string FilterIllegalCharsInFileName(string FileName)
        {
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"[^a-zA-Z0-9\-]");
            return regex.Replace(FileName, "_");
        }

        public static bool CheckOutItemFromSCC(ProjectItem item)
        {
            try
            {
                //Check source control
                EnvDTE80.DTE2 dte2 = (EnvDTE80.DTE2)item.DTE;
                bool b = dte2.SourceControl.IsItemUnderSCC(Common.GetProjectItemPath(item));
                if (b)
                {
                    if (!dte2.SourceControl.IsItemCheckedOut(Common.GetProjectItemPath(item)))
                    {
                        if (MessageBox.Show("Item '" + GetProjectItemPath(item, true) + "' will be checked out. Do you want to continue?", "Prompt", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes)
                        {
                            dte2.SourceControl.CheckOutItem(Common.GetProjectItemPath(item));
                        }
                        else
                        {
                            MessageBox.Show("Operation cancelled!", "Message", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                            return false;
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error checking out item " + item.Name + ". Info: " + ex.ToString(), "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return false;
            }
        }

        public static string GetTargetPath(Project proj)
        {
            string project_path = proj.Properties.Item("LocalPath").Value.ToString();
            string target_file_name = proj.Properties.Item("OutputFileName").Value.ToString();
            string output_path = proj.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();

            return project_path + output_path + target_file_name;
        }

        public static ProjectItem GetEventReceiversFolder(Project project)
        {
            ProjectItem item = null;

            string[] arr = C_PROJECT_EVENT_RECEIVER_CODE_PATH.Split('\\');
            for (int i = 0; i < arr.Length; i++)
            {
                if (item == null)
                    item = project.ProjectItems.Item(arr[0]);
                else
                    item = item.ProjectItems.Item(arr[i]);
            }

            return item;
        }

        public static ProjectItem CreateProjectItemPath(Project project, string path)
        {
            string[] arr = path.Split('\\');

            ProjectItem item;
            try
            {
                item = project.ProjectItems.Item(arr[0]);
            }
            catch
            {
                item = project.ProjectItems.AddFolder(arr[0], Constants.vsProjectItemKindPhysicalFolder);
            }

            for (int i = 1; i < arr.Length; i++)
            {
                try
                {
                    item = item.ProjectItems.Item(arr[i]);
                }
                catch
                {
                    item = item.ProjectItems.AddFolder(arr[i], Constants.vsProjectItemKindPhysicalFolder);
                }
            }

            return item;
        }

        public static string GetWSPToolsPath()
        {
            string ret = string.Empty;
            RegistryKey regkey = Registry.LocalMachine.OpenSubKey("Software\\WSPTools", false);
            if (regkey != null)
            {
                ret = regkey.GetValue("WSPToolsPath") as string;
            }

            return ret;
        }

        public static string GetInstallationKey(string key, bool bThrowExceptionIfNotExists)
        {
            string ret = null;
            try
            {
                RegistryKey regkey = Registry.LocalMachine.OpenSubKey("Software\\SPVisualDev", false);
                if (regkey == null)
                    regkey = Registry.CurrentUser.OpenSubKey("Software\\SPVisualDev", false);

                if (regkey == null)
                {
                    throw new Exception("Required registry key is not present.");
                }
                else
                {
                    ret = regkey.GetValue(key).ToString();
                }
            }
            catch 
            {
                if (bThrowExceptionIfNotExists)
                    throw;
            }

            return ret;
        }

        public static bool CheckIfInsideFeaturesFolder(ProjectItem Item)
        {
            ProjectItem parent = (ProjectItem)Item.Collection.Parent;
            while (parent != null && parent.Name.ToLower() != "features")
            {
                try
                {
                    parent = (ProjectItem)parent.Collection.Parent;
                }
                catch
                {
                    return false;
                }
            }

            return (parent != null);
        }

        public static void SaveXmlIndented(ref XmlDocument xdoc, string path)
        {
            XmlWriter writer = null;
            try
            {
                XmlWriterSettings settings = new XmlWriterSettings();
                settings.NewLineHandling = NewLineHandling.None;
                settings.NewLineOnAttributes = true;
                settings.IndentChars = "\t";
                settings.Indent = true;

                writer = XmlTextWriter.Create(path, settings);
                //writer.Formatting = Formatting.Indented;



                //xdoc.PreserveWhitespace = true;
                xdoc.Save(writer);
            }
            finally
            {
                if (writer != null)
                    writer.Close();
            }
        }

        public static string GetProjectGlobalConfigKey(Project project, string Key)
        {
            if (project.Globals.get_VariableExists(C_GLOBAL_CONFIG_KEY_PREFIX + Key))
            {
                string ret = project.Globals[C_GLOBAL_CONFIG_KEY_PREFIX + Key] as string;
                if (string.IsNullOrEmpty(ret))
                    return string.Empty;
                else
                    return ret;
            }
            else
                return string.Empty;
        }

        public static void SetProjectGlobalConfigKey(Project project, string Key, string Value, bool Persist)
        {
            project.Globals[C_GLOBAL_CONFIG_KEY_PREFIX + Key] = Value;
            project.Globals.set_VariablePersists(C_GLOBAL_CONFIG_KEY_PREFIX + Key, Persist);
        }

        public static void SetNamespaceInCodeFile(ref ProjectItem Item, string Namespace)
        {
            EnvDTE80.FileCodeModel2 file = (EnvDTE80.FileCodeModel2)Item.FileCodeModel;
            foreach (CodeElement element in file.CodeElements)
            {
                if (element is CodeNamespace)
                {
                    EditPoint start = element.StartPoint.CreateEditPoint();
                    start.ReplaceText(start.LineLength, "namespace " + Namespace, (int)vsEPReplaceTextOptions.vsEPReplaceTextAutoformat);

                    return;

                }
            }
        }

        public static ProjectItem AddNewCulture(string ResourceFile, string cultureInfo, Project project, ProjectItem FeatureNode)
        {
            bool isLocalResource = (FeatureNode != null);
            ProjectItem resource_folder = null;

            string res_file_name = ResourceFile;
            if (!string.IsNullOrEmpty(cultureInfo))
                res_file_name += "." + cultureInfo;
            res_file_name += ".resx";

            if (isLocalResource)
            {
                resource_folder = Common.CreateProjectItemPath(project, "12\\TEMPLATE\\Features\\" + FeatureNode.Name + "\\Resources");

                try
                {
                    ProjectItem resources = resource_folder.ProjectItems.Item(res_file_name);
                    if (resources != null)
                    {
                        throw new Exception("A resource file with the same name exists already. Operation aborted.");
                    }
                }
                catch { }
            }
            else
            {
                resource_folder = Common.CreateProjectItemPath(project, "12\\Resources");
                try
                {
                    ProjectItem resources = resource_folder.ProjectItems.Item(res_file_name);
                    if (resources != null)
                    {
                        throw new Exception("A resource file with the same name exists already. Operation aborted.");
                    }
                }
                catch { }
            }

            if (resource_folder != null)
            {
                string template_path = Common.GetItemTemplatePath(resource_folder.ContainingProject, "Resource.zip", false);
                resource_folder.ProjectItems.AddFromTemplate(template_path, res_file_name);

                try
                {
                    resource_folder.ProjectItems.Item(res_file_name).Document.Close(vsSaveChanges.vsSaveChangesYes);
                }
                catch { }

                return resource_folder.ProjectItems.Item(res_file_name);
            }
            else
            {
                return null;
            }

        }

        public static Dictionary<string, string> GetPropertiesFromObject(object Object)
        {
            Dictionary<string, string> properties = new Dictionary<string, string>();

            foreach (PropertyInfo pInfo in Object.GetType().GetProperties())
            {
                try
                {
                    object v = pInfo.GetValue(Object, null);
                    if (v != null)
                    {
                        properties.Add(pInfo.Name, v.ToString());
                    }
                    else
                    {
                        properties.Add(pInfo.Name, string.Empty);
                    }
                }
                catch
                {
                }
            }

            return properties;
        }
    }
}

